package wiki.kaizen.cloud.shiro.stateless.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;
import wiki.kaizen.cloud.shiro.stateless.properties.SecurityProperties;
import wiki.kaizen.cloud.shiro.stateless.util.RedisUtil;

import javax.annotation.PostConstruct;
import java.nio.charset.Charset;

/**
 * redis 缓存配置类
 * @author  xeepoo
 * */
@Configuration
public class RedisConfig {

    private final  SecurityProperties.Redis redis;

    public RedisConfig(SecurityProperties securityProperties) {
        this.redis = securityProperties.getRedis();
    }

    /*
    * 配置连接池
    * */
    private JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(redis.getMaxTotal());
        config.setMinIdle(redis.getMinIdle());
        config.setMaxIdle(redis.getMaxIdle());
        config.setMaxWaitMillis(redis.getMaxWaitMillis());
        return config;
    }

    private RedisConnectionFactory connectionFactory(){
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(
            redis.getHost(), redis.getPort()
        );
        config.setDatabase(redis.getDatabase());
        if(!StringUtils.isEmpty(redis.getPassword())){
            config.setPassword(redis.getPassword());
        }

        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder builder =
            (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
        builder.poolConfig(
            jedisPoolConfig()
        );
        return new JedisConnectionFactory(
            config , builder.build()
        );
    }
    /*
    * 设置参数
    * */
    @PostConstruct
    public void templateBuild(){
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(
            connectionFactory()
        );
        template.setValueSerializer(
            this.redisSerializer(Object.class)
        );
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        RedisUtil.setRedisTemplate(template);
    }

    /**
     * fastjson 序列化
     * */
    public <T> RedisSerializer<T>  redisSerializer(Class<T> clazz){
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        return  new RedisSerializer<T>() {

            public byte[] serialize(T t) throws SerializationException {
                if (t == null) {
                    return new byte[0];
                }
                return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(Charset.forName("UTF-8"));
            }

            public T deserialize(byte[] bytes) throws SerializationException {
                if (bytes == null || bytes.length <= 0) {
                    return null;
                }
                String str = new String(bytes, Charset.forName("UTF-8"));

                return JSON.parseObject(str, clazz);
            }

        };
    }
    public StringRedisTemplate stringRedisTemplate(){
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(
            connectionFactory()
        );

        return template;
    }
}
